package com.portal.framework.util;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.dao.CannotAcquireLockException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.InvalidResultSetAccessException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

import com.portal.framework.exception.AppException;

/**
 * 工具类: 获得JDBC连接,关闭连接,资源清理
 * 
 * @author 卢烁波
 * @date 2007-3-10
 */
public class DBUtil implements ApplicationContextAware {
	// spring的上下文
	private static ApplicationContext applicationContext;

	private static final Log log = LogFactory.getLog(DBUtil.class);

	private static final SQLErrorCodeSQLExceptionTranslator translator = new SQLErrorCodeSQLExceptionTranslator(
			"Oracle");

	/**
	 * 异常转换
	 * 
	 * @param ex spring框架封装的数据访问异常
	 * @return 系统自定义应用程序异常
	 */
	public static AppException convertException(DataAccessException ex) {
		if (ex.getCause() instanceof AppException) {
			return (AppException) ex.getCause();
		} else if (ex instanceof UncategorizedSQLException) {
			System.err.println(((SQLException) ex.getCause())
					.getLocalizedMessage());
			return new AppException("以下SQL语句执行错误,请与系统管理员联系: \n"
					+ ((UncategorizedSQLException) ex).getCause()
							.getLocalizedMessage());
		} else if (ex.getCause() instanceof SQLException) {
			System.err.println(((SQLException) ex.getCause())
					.getLocalizedMessage());
			int errorCode = ((SQLException) ex.getCause()).getErrorCode();
			switch (errorCode) {
			case 942:
				return new AppException("20007");
			case 1:
				return new AppException("20009");
			case 1400:
				return new AppException("20010");
			case 2292:
				return new AppException("20011");
			}
		} else if (ex instanceof ObjectOptimisticLockingFailureException) {
			return new AppException("20008");
		} else if (ex instanceof DataAccessResourceFailureException) {
			return new AppException("20001");
		} else if (ex instanceof DataIntegrityViolationException) {
			return new AppException("20002");
		} else if (ex instanceof BadSqlGrammarException) {
			return new AppException("20003");
		} else if (ex instanceof InvalidResultSetAccessException) {
			return new AppException("20004");
		} else if (ex instanceof CannotAcquireLockException) {
			return new AppException("20005");
		}
		return new AppException(ex.getMessage());
	}

	/**
	 * 异常转换
	 * 
	 * @param ex JDBC异常
	 * @return 系统自定义应用程序异常
	 */
	public static DataAccessException convertException(SQLException ex) {
		return translator.translate(null, null, ex);
	}

	/**
	 * 转换HibernateException 到 AppException
	 * 
	 * @param ex Hibernate操作失败所引发的异常
	 * @return 系统自定义应用程序异常
	 */
	public static DataAccessException convertException(HibernateException ex) {
		if (ex instanceof JDBCException) {
			return convertJdbcAccessException((JDBCException) ex);
		}
		return SessionFactoryUtils.convertHibernateAccessException(ex);
	}

	/**
	 * 转换JDBCException到DataAccessException
	 * 
	 * @param ex JDBCException that occured, wrapping a SQLException
	 * @return the corresponding DataAccessException instance
	 * @see #setJdbcExceptionTranslator
	 */
	protected static DataAccessException convertJdbcAccessException(
			JDBCException ex) {
		return translator.translate("Hibernate operation: " + ex.getMessage(),
				null, ex.getSQLException());
	}

	/**
	 * 实现接口方法 设置ApplicationContext,由spring调用
	 */
	public void setApplicationContext(ApplicationContext context)
			throws BeansException {
		applicationContext = context;
	}

	/**
	 * 查找配置中的BEAN
	 * 
	 * @param clazz 类名
	 * @return BEAN
	 */
	public static Object getBeanByClass(Class clazz) {
		Map map = applicationContext.getBeansOfType(clazz);
		for (Iterator iter = map.keySet().iterator(); iter.hasNext();) {
			Object bean = map.get(iter.next());
			if (null != bean) {
				return bean;
			}
		}
		return null;
	}

	/**
	 * 查找配置中的BEAN
	 * 
	 * @param name BEAN名称
	 * @return BEAN
	 */
	public static Object getBeanByName(String name) {
		return applicationContext.getBean(name);
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	/**
	 * 反射方法
	 * 
	 * @param clazz 类名
	 * @param methodName 方法名
	 * @return 方法
	 */
	public static Method getMethod(Class clazz, String methodName) {
		return BeanUtils.findMethodWithMinimalParameters(clazz, methodName);
	}

	public static void closePreparedStatement(PreparedStatement ps) {
		if (ps != null) {
			try {
				ps.close();
			} catch (SQLException e) {
			}
		}
	}

	public static void closeStatement(Statement s) {
		if (s != null) {
			try {
				s.close();
			} catch (SQLException e) {
			}
		}
	}

	public static void closeConnection(Connection conn) {
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
			}
		}
	}

	public static void rollbackConnection(Connection conn) {
		if (conn != null) {
			try {
				conn.rollback();
			} catch (SQLException e) {
			}
		}
	}

}
